package com.example.testone.utils

import androidx.lifecycle.ViewModel
import com.example.testone.viewModels.SettingViewModel
import javax.inject.Inject
import javax.inject.Singleton

class MaskIntro(val name:String, val code:String, val protocolHash:HashMap<Byte,ProtocolIntro>)

open class ProtocolIntro(val code:String, val name:String){
    val  TAG = "ProtocolIntro"

//    open fun exec(bytes:ByteArray= byteArrayOf()){
//        if ( bytes.size == 5 ) {
//            //发送指令
//            val last_all_byte =bytes.plus( ByteUtil.sign(bytes))
//
//            MyLog.print(TAG,  ByteUtil.toHexStr(last_all_byte))
//            DeviceFlow.sendMsg(last_all_byte)
//        }
//    }

    open fun command(viewModel:ViewModel,dataByte0:Byte,dataByte1:Byte,dataByte2:Byte,dataByte3:Byte,dataByte4:Byte){

    }


}

@Singleton
class DeviceProtocol @Inject constructor(val serialPortUtil: MySerialPort) {
    val TAG = "DeviceProtocol"

    val info by lazy {
        val hashMap = HashMap<Byte, MaskIntro>()

        hashMap.put ( 0x10 ,  MaskIntro("交互码","CTRL_ACK_NAK_MASK",hashMapOf(
            Pair(0x11, object :ProtocolIntro("CTRL_CMD_CRC_ERR","数据校验出错，需重新发送数据"){
                override fun command( viewModel: ViewModel, dataByte0:Byte, dataByte1:Byte, dataByte2:Byte, dataByte3:Byte, dataByte4:Byte ) {
                    if(viewModel is SettingViewModel){
//                        viewModel.isOpening.value = true
                    }
                }
            }),
            Pair(0x06, object :ProtocolIntro("CTRL_CMD_ACK","应答码"){
                override fun command( viewModel: ViewModel, dataByte0:Byte, dataByte1:Byte, dataByte2:Byte, dataByte3:Byte, dataByte4:Byte ) {
                    if(viewModel is SettingViewModel){
//                        viewModel.isOpening.value = true
                    }
                }
            }),
            Pair(0x15, object :ProtocolIntro("CTRL_CMD_NAK","出错码"){
                override fun command( viewModel: ViewModel, dataByte0:Byte, dataByte1:Byte, dataByte2:Byte, dataByte3:Byte, dataByte4:Byte ) {
                    if(viewModel is SettingViewModel){
//                        viewModel.isOpening.value = true
                    }
                }
            }),
            Pair(0x08, ProtocolIntro("HEART","心跳包传递数据")),
        )))
        hashMap.put ( 0x60 ,  MaskIntro("按键控制","CTRL_KEY_MASK",hashMapOf(
            Pair(0x61, ProtocolIntro("CTRL_KEY_POWER_PRESS","电源按键按下")),
            Pair(0x62, ProtocolIntro("CTRL_KEY_POWER_RELEASE","电源按键释放")),
            Pair(0x63, ProtocolIntro("CTRL_KEY_WORK_PRESS","工作按键按下")),
            Pair(0x64, ProtocolIntro("CTRL_KEY_WORK_RELEASE","工作按键释放")),
            Pair(0x65, ProtocolIntro("CTRL_KEY_TIME_UP_PRESS","时间+按键按下")),
            Pair(0x66, ProtocolIntro("CTRL_KEY_TIME_UP_RELEASE","时间+按键释放")),
            Pair(0x67, ProtocolIntro("CTRL_KEY_TIME_DOWN_PRESS","时间-按键按下")),
            Pair(0x68, ProtocolIntro("CTRL_KEY_TIME_DOWN_RELEASE","时间-按键释放")),
            Pair(0x69, ProtocolIntro("CTRL_KEY_TEMP_UP_PRESS","温度+按键按下")),
            Pair(0x6A, ProtocolIntro(" CTRL_KEY_TEMP_UP_RELEASE","温度+按键释放")),
            Pair(0x6B, ProtocolIntro(" CTRL_KEY_TEMP_DOWN_PRESS","温度-按键按下")),
            Pair(0x6C, ProtocolIntro(" CTRL_KEY_TEMP_DOWN_RELEASE","温度-按键释放")),
            Pair(0x6D, ProtocolIntro(" CTRL_KEY_C_F_PRESS","温度C/F按键按下")),
            Pair(0x6E, ProtocolIntro(" CTRL_KEY_C_F_RELEASE","温度C/F按键释放")),
        )))
        hashMap.put ( 0x80.toByte() ,  MaskIntro("数据输出","CTRL_DATA_MASK",hashMapOf(
            Pair(0x81.toByte(), ProtocolIntro("CTRL_DATA_CTEMP","当前温度值")),
            Pair(0x82.toByte(), object :ProtocolIntro("CTRL_DATA_STEMP","设定温度值"){
                override fun command( viewModel: ViewModel, dataByte0:Byte, dataByte1:Byte, dataByte2:Byte, dataByte3:Byte, dataByte4:Byte ) {
                    if(viewModel is SettingViewModel){
                        //当前设置温度与板子温度不一致-重新设置
                        if(viewModel.wdNumber.value != dataByte2.toInt()){
                            viewModel.wdNumber.postValue(viewModel.wdNumber.value)
                        }
                    }
                }
            }),
            Pair(0x83.toByte(), ProtocolIntro("CTRL_DATA_TEMP_C","温度值后缀C")),
            Pair(0x84.toByte(), ProtocolIntro("CTRL_DATA_TEMP_F","温度值后缀F")),
            Pair(0x85.toByte(), ProtocolIntro("CTRL_DATA_TEMP_N_DISP","温度值不显示")),
            Pair(0x86.toByte(), ProtocolIntro("CTRL_DATA_CTIME","当前时间值")),
            Pair(0x87.toByte(), ProtocolIntro("CTRL_DATA_STIME","设定时间值")),
            Pair(0x88.toByte(), ProtocolIntro("CTRL_DATA_TIME_N_DISP","时间值不显示")),
            Pair(0x89.toByte(), ProtocolIntro("HEART","心跳包传递数据")),
        )))

        //命令控制
        hashMap.put ( 0x20 ,  MaskIntro("命令控制","CTRL_CMD_MASK",hashMapOf(
            Pair(0x21, ProtocolIntro("CTRL_CMD_OPEN","开机")),
            Pair(0x22, ProtocolIntro("CTRL_CMD_CLOSE","关机")),
            Pair(0x23, ProtocolIntro("CTRL_CMD_TEMP_SET","设定温度")),
            Pair(0x24, ProtocolIntro("CTRL_CMD_TIME_SET","设定时间")),
            Pair(0x25, ProtocolIntro("CTRL_CMD_TEMP_C","切换到C单位显示温度值")),
            Pair(0x26, ProtocolIntro("CTRL_CMD_TEMP_F","切换到F单位显示温度值")),
            Pair(0x27, ProtocolIntro("CTRL_CMD_STANDBY","待机命令")),
            Pair(0x28, ProtocolIntro("CTRL_CMD_WORK","工作命令")),
            Pair(0x29, ProtocolIntro("CTRL_CMD_STOP","停止工作命令")),
            Pair(0x2A, ProtocolIntro("CTRL_CMD_DATA_AUTOSND","数据自动发送")),
            Pair(0x2B, ProtocolIntro("CTRL_CMD_DATA_QUERYSND","数据采用查询方式发送")),
            Pair(0x2C, ProtocolIntro("CTRL_CMD_LIGHT_INTENSITY_UP","照明灯光强度+")),
            Pair(0x2D, ProtocolIntro("CTRL_CMD_LIGHT_INTENSITY_DOWN","照明灯光强度-")),
            Pair(0x2E, ProtocolIntro("CTRL_CMD_LIGHT_INTENSITY_SETTING","设置照明灯光强度-")),
        )))

        //开关控制
        hashMap.put ( 0x30 ,   MaskIntro("开关控制","CTRL_SWITCH_MASK",hashMapOf(
            Pair(0x31, ProtocolIntro("CTRL_SWITCH_UVLAMP_OPEN","UV灯开")),
            Pair(0x32, ProtocolIntro("CTRL_SWITCH_UVLAMP_CLOSE","UV灯关")),
            Pair(0x33, ProtocolIntro("CTRL_SWITCH_ROOFLAMP_OPEN","ROOF灯开")),
            Pair(0x34, ProtocolIntro("CTRL_SWITCH_ROOFLAMP_CLOSE","ROOF灯关")),
            Pair(0x35, ProtocolIntro("CTRL_SWITCH_HEATPWM_OPEN","PWM加热开")),
            Pair(0x36, ProtocolIntro("CTRL_SWITCH_HEATPWM_CLOSE","PWM加热关")),
            Pair(0x36, ProtocolIntro("CTRL_SWITCH_HEATPWM_CLOSE","PWM加热关")),
            Pair(0x37, ProtocolIntro("CTRL_SWITCH_PANHEAT_OPEN","PAN加热开")),
            Pair(0x38, ProtocolIntro("CTRL_SWITCH_PANHEAT_CLOSE","PAN加热关")),
            Pair(0x39, ProtocolIntro("CTRL_SWITCH_FAN_OPEN","PAN开")),
            Pair(0x3A, ProtocolIntro("CTRL_SWITCH_HEAT_OPEN","加热开")),
            Pair(0x3B, ProtocolIntro("CTRL_SWITCH_HEAT_CLOSE","加热关")),
            Pair(0x3C, ProtocolIntro("CTRL_SWITCH_COLOR_OPEN","颜色灯开")),
            Pair(0x3D, ProtocolIntro("CTRL_SWITCH_COLOR_CLOSE","颜色灯关")),
            Pair(0x3E, ProtocolIntro("CTRL_SWITCH_STATE_OPEN","状态灯开")),
            Pair(0x3F, ProtocolIntro("CTRL_SWITCH_STATE_CLOSE","状态灯关")),
        )))
        //查询控制
        hashMap.put ( 0x70 ,  MaskIntro("查询控制","CTRL_QUERY_MASK",hashMapOf(
            Pair(0x71, ProtocolIntro("CTRL_QUERY_POWER_STATE","开机状态查询命令")),
            Pair(0x72, ProtocolIntro("CTRL_QUERY_WORK_STATE","工作状态查询命令")),
            Pair(0x73, ProtocolIntro("CTRL_QUERY_GET_CTEMP","获取当前温度值命令")),
            Pair(0x74, ProtocolIntro("CTRL_QUERY_GET_STEMP","获取设定温度值命令")),
            Pair(0x75, ProtocolIntro("CTRL_QUERY_GET_CTIME","获取当前时间值命令")),
            Pair(0x76, ProtocolIntro("CTRL_QUERY_GET_STIME","获取设定时间值命令")),
            Pair(0x77, ProtocolIntro("CTRL_QUERY_ERR_INFO","故障信息查询命令")),
        )))
        //状态输出
        hashMap.put ( 0x90.toByte() ,  MaskIntro("状态输出","CTRL_STATE_MASK",hashMapOf(
            Pair(0x91.toByte(), object:ProtocolIntro("CTRL_STATE_POWER_ON","开机状态"){
                override fun command( viewModel: ViewModel, dataByte0:Byte, dataByte1:Byte, dataByte2:Byte, dataByte3:Byte, dataByte4:Byte ) {
                    if(viewModel is SettingViewModel){
                        if(viewModel.isBootState.value!=true){
                            viewModel.isBootState.postValue(true)

                        }
                        viewModel.checkRecBootTime = Helper.getCurrentTimeStamp()

                    }
                }
            }),
            Pair(0x92.toByte(),  object:ProtocolIntro("CTRL_STATE_POWER_OFF","关机状态") {
                override fun command( viewModel: ViewModel, dataByte0:Byte, dataByte1:Byte, dataByte2:Byte, dataByte3:Byte, dataByte4:Byte ) {
                    if(viewModel is SettingViewModel){
                        if(viewModel.isBootState.value!=false){
                            viewModel.isBootState.postValue(false)
                        }

                        if(viewModel.isWorking.value!=false){
                            viewModel.isWorking.postValue(false)
                        }
                        viewModel.checkRecBootTime = Helper.getCurrentTimeStamp()

                    }
                }
            }),
            Pair(0x93.toByte(),object: ProtocolIntro("CTRL_STATE_WORK","工作状态"){
                override fun command( viewModel: ViewModel, dataByte0:Byte, dataByte1:Byte, dataByte2:Byte, dataByte3:Byte, dataByte4:Byte ) {
                    if(viewModel is SettingViewModel){
                        if(viewModel.isBootState.value!=true){
                            viewModel.isBootState.postValue(true)
                        }
                        viewModel.checkRecBootTime = Helper.getCurrentTimeStamp()
                        //更新接收时间
                        viewModel.checkRecWorkTime = Helper.getCurrentTimeStamp()

                        if (viewModel.isWorking.value == false ) {
                            viewModel.isWorking.postValue(true)
                        }
                    }
                }
            }),
            Pair(0x94.toByte(),object: ProtocolIntro("CTRL_STATE_STOP","待机状态"){
                override fun command( viewModel: ViewModel, dataByte0:Byte, dataByte1:Byte, dataByte2:Byte, dataByte3:Byte, dataByte4:Byte ) {
                    if(viewModel is SettingViewModel){
                        if(viewModel.isBootState.value!=true){
                            viewModel.isBootState.postValue(true)
                        }
                        viewModel.checkRecBootTime = Helper.getCurrentTimeStamp()
                        //更新接收时间
                        viewModel.checkRecWorkTime = Helper.getCurrentTimeStamp()
                        if (viewModel.isWorking.value == true ) {
                            viewModel.isWorking.postValue(false)
                        }
                    }
                }
            }),
        )))
        //错误信息输出
        hashMap.put ( 0xa0.toByte() ,  MaskIntro("错误信息输出","ERR_STATE_MASK",hashMapOf(
            Pair(0xa1.toByte(), ProtocolIntro("ERR_STATE_TEMP_OPEN","温度传感器断开")),
            Pair(0xa2.toByte(), ProtocolIntro("ERR_STATE_TEMP_CLOSE","温度传感器短路")),
            Pair(0xa3.toByte(), ProtocolIntro("ERR_STATE_TEMP_HIGH","当前温度值高于设定温度")),
            Pair(0xa4.toByte(), ProtocolIntro("ERR_STATE_TEMP_LOW","当前温度低于-10度")),
        )))
        hashMap
    }

    fun getModeObj(maskCode:Byte,controlCode:Byte):Pair<MaskIntro?,ProtocolIntro?> {
        val maskIntro = info.get(maskCode)
        var protocol:ProtocolIntro? = null
        maskIntro?.let {
            protocol = it.protocolHash.get(controlCode)

        }
        return Pair(maskIntro,protocol)
    }

    fun command(maskCode:Byte,controlCode:Byte,dataCode:ByteArray = byteArrayOf() ,callback:((MaskIntro?,ProtocolIntro?)->Unit)?=null){
        val maskIntro = info.get(maskCode)
        var protocol:ProtocolIntro? = null
        var exists = false
        maskIntro?.let {
//                println(it.name)
            protocol = it.protocolHash.get(controlCode)
            protocol?.let { pro->
                exists = true
//                    println(pro.code)
            }
        }

        if(exists){
            val bytes = byteArrayOf(maskCode,controlCode).plus(dataCode)
            val sendBoolean = serialPortUtil.serialPort.sendBytes(bytes.plus(ByteUtil.sign(bytes)))

            MyLog.print("deviceCommandSend","發送指令:-${maskIntro!!.name}->:${maskIntro.code}->:${protocol!!.name}->:${protocol!!.code}--hexStr${ByteUtil.toHexStr(bytes.plus(ByteUtil.sign(bytes)))}")
//                println("指令不存在:-maskCode:${maskCode}-controlCode:${controlCode}-dataCode:${dataCode}-")
            if (callback != null) {
                callback(maskIntro,protocol)
            }
        }else{
            MyLog.print("deviceCommandSend","指令不存在:-maskCode:${maskCode}-controlCode:${controlCode}-dataCode:${dataCode}-")
        }


    }


    fun speCommand(viewModel:ViewModel,dataByte0:Byte,dataByte1:Byte,dataByte2:Byte,dataByte3:Byte,dataByte4:Byte){
        MyLog.print("SPE"+TAG,"dataByte0:-${ByteUtil.toHexStr(dataByte0)}")
            val current_minute = dataByte1.toInt()
        if(dataByte0 == 0x86.toByte()){
                if(viewModel is SettingViewModel){
                    //正在进行
                    if(viewModel.settingRunningState.value==1){
//                        if ( current_minute != viewModel.countdownTime.value){
//                            viewModel.countdownTime.postValue(current_minute)
//                        }
                    }
                }
//                MyLog.print("SPE"+TAG,"当前时间值dataByte0:-${ByteUtil.toHexStr(dataByte0)}->dataByte1:${ByteUtil.toHexStr(dataByte1)}->time:${dataByte1.toInt()}->dataByte2:${dataByte2.toInt()}->dataByte3:${dataByte3.toInt()}->current_minute${current_minute}")
        } else if(dataByte0 == 0x87.toByte()){

        } else if(dataByte0 == 0x81.toByte()){
            if(viewModel is SettingViewModel){
//                if(viewModel.wdNumber.value!=0){
                    viewModel.wdNumber.postValue(dataByte2.toInt())
//                }
            }
        } else if(dataByte0 == 0x88.toByte()){
                if(viewModel is SettingViewModel){
                    if(viewModel.countdownState.value!=0){
                        viewModel.countdownState.postValue(0)
                    }
                }
                MyLog.print("SPE"+TAG,"时间值不显示dataByte0:-${ByteUtil.toHexStr(dataByte0)}->dataByte1:${ByteUtil.toHexStr(dataByte1)}->time:${dataByte1.toInt()}")
        }
    }


}